home *** CD-ROM | disk | FTP | other *** search
/ Aminet 1 (Walnut Creek) / Aminet - June 1993 [Walnut Creek].iso / aminet / comm / misc / xqsrc931030.lzh / library / session.c < prev    next >
C/C++ Source or Header  |  1993-01-29  |  13KB  |  533 lines

  1. /*
  2.  *    Name:                session.c
  3.  *
  4.  * Description:    Session management functions for xferq.library
  5.  *
  6.  * Copyright:        1992-1993 by David Jones.
  7.  *
  8.  * Distribution:
  9.  *        This program is free software; you can redistribute it and/or modify
  10.  *        it under the terms of the GNU General Public License as published by
  11.  *        the Free Software Foundation; either version 2 of the License, or
  12.  *        (at your option) any later version.
  13.  *
  14.  *        This program is distributed in the hope that it will be useful,
  15.  *        but WITHOUT ANY WARRANTY; without even the implied warranty of
  16.  *        MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17.  *        GNU General Public License for more details.
  18.  *
  19.  *        You should have received a copy of the GNU General Public License
  20.  *        along with this program; if not, write to:
  21.  *
  22.  *                The Free Software Foundation        David Jones
  23.  *                675 Mass Ave                            6730 Tooney Drive
  24.  *                Cambridge, MA                            Orleans, Ontario
  25.  *                02139                                        K1C 6R4
  26.  *                USA                                        Canada
  27.  *
  28.  *    Usenet:    gnu@prep.ai.mit.edu                    dej@qpoint.ocunix.on.ca
  29.  *    Fidonet:                                                1:163/109.8
  30.  *
  31.  *        $Log: $
  32.  *
  33.  */
  34.  
  35. #include <exec/types.h>
  36. #include "xferq.h"
  37. #include "xferqint.h"
  38. #include "xferq_pragmas.h"
  39. #include <proto/exec.h>
  40. #include <utility/tagitem.h>
  41. #include <proto/utility.h>
  42. #include <exec/lists.h>
  43. #include "execlists.h"
  44. #include <exec/semaphores.h>
  45.  
  46. extern struct SignalSemaphore QueueLock;
  47. extern struct MinList QueueList;
  48.  
  49. void PostCreateSession(struct Session *session)
  50. /*
  51.  *    In:    session            Pointer to session to initialize
  52.  *
  53.  *    Does:    Initializes a session structure once created.  This involves
  54.  *            setting up the site list.
  55.  */
  56. {
  57.  
  58.     NEWLIST(&session->sessList);
  59. }
  60.  
  61.  
  62. void PreDropSession(struct Session *session)
  63. /*
  64.  *    In:    session            Pointer to session to drop
  65.  *
  66.  * Does:    Ends all sessions on the given cookie.
  67.  */
  68. {
  69.  
  70.     XfqEndSession(session, NULL);
  71. }
  72.  
  73.  
  74. ULONG __saveds __asm LIBSessionUp(register __a0 struct NetAddress *addr)
  75. /*
  76.  *    In:    addr        A0        Address to test existence of session on
  77.  *
  78.  *    Does:    Returns TRUE if there's a session active to the given address.
  79.  *            Returns FALSE otherwise.
  80.  */
  81. {
  82. struct SiteNode *sn;
  83. BOOL result;
  84.  
  85.     ObtainSemaphore(&QueueLock);
  86.     sn = FindSiteQueue(addr);
  87.     if (sn) {
  88.         result = sn->numSessions != 0;
  89.     }
  90.     else {
  91.         result = FALSE;
  92.     }
  93.     ReleaseSemaphore(&QueueLock);
  94.     return result;
  95. }
  96.  
  97.  
  98. struct SessNode *FindSessNode(struct Session *session,
  99.     struct NetAddress *addr)
  100. /*
  101.  *    In:    session            Session cookie to scan
  102.  *            addr                Address to search for
  103.  *
  104.  * Does:    Searches for the address in the session cookie and returns
  105.  *            a pointer to the session node if found and NULL otherwise.
  106.  */
  107. {
  108. struct SessNode *sn;
  109.  
  110.     sn = FIRST(&session->sessList);
  111.     while (NEXT(sn)) {
  112.         if (!XfqCmpAddressTags(addr, sn->addr,
  113.             XQ_Mandatory, XQADDR_ALLBUTUSER,
  114.             TAG_DONE)) {
  115.             return sn;
  116.         }
  117.         sn = NEXT(sn);
  118.     }
  119.     return NULL;
  120. }
  121.  
  122.  
  123. void AddSessNodeSorted(struct Session *session, struct SessNode *node,
  124.     struct SessNode *last)
  125. /*
  126.  *    In:    session            Session to add node to
  127.  *            node                Pointer to node to add
  128.  *            last                Pointer to last node added
  129.  *
  130.  * Does:    Adds the node to the session in sorted order.  The last node
  131.  *            is given for performance purposes.
  132.  */
  133. {
  134. struct MinList *list;
  135. struct SessNode *probe;
  136.  
  137.     list = &session->sessList;
  138.     probe = FIRST(list);
  139.     if (!NEXT(probe)) {
  140.         ADDHEAD(list, node);
  141.         return;
  142.     }
  143.     if (XfqCmpAddress(node->addr, probe->addr, NULL) < 0) {
  144.         ADDHEAD(list, node);
  145.         return;
  146.     }
  147.     probe = LAST(list);
  148.     if (XfqCmpAddress(node->addr, probe->addr, NULL) < 0) {
  149.         ADDTAIL(list, node);
  150.         return;
  151.     }
  152.     if (XfqCmpAddress(node->addr, last->addr, NULL) > 0) {
  153.         probe = NEXT(last);
  154.         while (XfqCmpAddress(node->addr, probe->addr, NULL) > 0) {
  155.             probe = NEXT(probe);
  156.         }
  157.         INSERT(list, node, PREV(probe));
  158.         return;
  159.     }
  160.     else {
  161.         probe = PREV(last);
  162.         while (XfqCmpAddress(node->addr, probe->addr, NULL) < 0) {
  163.             probe = PREV(probe);
  164.         }
  165.         INSERT(list, node, probe);
  166.     }
  167. }
  168.  
  169.  
  170. ULONG __saveds __asm LIBBeginSession(register __a0 struct Session *session,
  171.     register __a1 struct TagItem *tags)
  172. /*
  173.  *    In:    session    A0        Session cookie to add address to
  174.  *            tags        A1        Taglist controlling operation
  175.  *
  176.  * Does:    Starts a session to the given site.  If the session is a public
  177.  *            session, then the fact that you have started a session will be
  178.  *            visible to all callers.  If the session started successfully,
  179.  *            the function returns TRUE.  Otherwise, it returns FALSE.
  180.  *
  181.  *            XQ_AddHead        Add the data to the front of the list in the
  182.  *                                session cookie.
  183.  *            XQ_AddTail        Add the data to the tail of the list in the
  184.  *                                session cookie.
  185.  *            XQ_AddSorted    Add each datum in sorted order.  This assumes the
  186.  *                                session cookie is already sorted.
  187.  *
  188.  *            In all cases, the data may be either an address or a session.
  189.  *            If a session, this is equivalent to performing the operation
  190.  *            will all addresses in the session.  More than one occurrence of
  191.  *            each operation tag is permitted.
  192.  */
  193. {
  194. struct MinList memList;
  195. BOOL public, result;
  196. struct TagItem *tag, *walk;
  197. struct SessNode *sn, *wsn, *tsn, *last;
  198. struct Session *source;
  199. struct SiteNode *sq;
  200.  
  201.     public = !(session->flags & XQSESS_PRIVATE);
  202.     /*
  203.      *    Prepass: ensure enough memory to go around.
  204.      */
  205.     NEWLIST(&memList);
  206.     result = TRUE;
  207.     walk = tags;
  208.     while (result && (tag = NextTagItem(&walk))) {
  209.         switch (tag->ti_Tag) {
  210.         case XQ_AddHead:
  211.         case XQ_AddTail:
  212.         case XQ_AddSorted:
  213.             source = (struct Session *)tag->ti_Data;
  214.             if (ObjectType(source) == XQO_ADDRESS) {
  215.                 sn = AllocMemory(sizeof(struct SessNode));
  216.                 if (sn) {
  217.                     ADDHEAD(&memList, sn);
  218.                 }
  219.                 else {
  220.                     result = FALSE;
  221.                 }
  222.             }
  223.             else {
  224.                 wsn = FIRST(&source->sessList);
  225.                 while (result && (tsn = NEXT(wsn))) {
  226.                     sn = AllocMemory(sizeof(struct SessNode));
  227.                     if (sn) {
  228.                         ADDHEAD(&memList, sn);
  229.                     }
  230.                     else {
  231.                         result = FALSE;
  232.                     }
  233.                     wsn = tsn;
  234.                 }
  235.             }
  236.             break;
  237.         }
  238.     }
  239.     if (!result) {
  240.         sn = FIRST(&memList);
  241.         while (tsn = NEXT(sn)) {
  242.             FreeMemory(sn);
  243.             sn = tsn;
  244.         }
  245.         SetErrorTags(tags);
  246.         return FALSE;
  247.     }
  248.     
  249.     if (public) {
  250.         ObtainSemaphore(&QueueLock);
  251.     }
  252.     
  253.     walk = tags;
  254.     last = NULL;
  255.     while (tag = NextTagItem(&walk)) {
  256.         switch (tag->ti_Tag) {
  257.         case XQ_AddHead:
  258.             if (ObjectType(tag->ti_Data) == XQO_ADDRESS) {
  259.                 sn = REMHEAD(&memList);
  260.                 sn->addr = (struct NetAddress *)tag->ti_Data;
  261.                 XfqCopyObject(sn->addr);
  262.                 ADDHEAD(&session->sessList, sn);
  263.                 if (public) {
  264.                     sq = FindSiteQueue(sn->addr);
  265.                     sq->numSessions++;
  266.                 }
  267.                 last = sn;
  268.             }
  269.             else {
  270.                 source = (struct Session *)tag->ti_Data;
  271.                 wsn = LAST(&source->sessList);
  272.                 while (tsn = PREV(wsn)) {
  273.                     sn = REMHEAD(&memList);
  274.                     sn->addr = wsn->addr;
  275.                     XfqCopyObject(sn->addr);
  276.                     ADDHEAD(&session->sessList, sn);
  277.                     if (public) {
  278.                         sq = FindSiteQueue(sn->addr);
  279.                         sq->numSessions++;
  280.                     }
  281.                     wsn = tsn;
  282.                 }
  283.                 last = sn;
  284.             }
  285.             break;
  286.         case XQ_AddTail:
  287.             if (ObjectType(tag->ti_Data) == XQO_ADDRESS) {
  288.                 sn = REMHEAD(&memList);
  289.                 sn->addr = (struct NetAddress *)tag->ti_Data;
  290.                 XfqCopyObject(sn->addr);
  291.                 ADDTAIL(&session->sessList, sn);
  292.                 if (public) {
  293.                     sq = FindSiteQueue(sn->addr);
  294.                     sq->numSessions++;
  295.                 }
  296.                 last = sn;
  297.             }
  298.             else {
  299.                 source = (struct Session *)tag->ti_Data;
  300.                 wsn = FIRST(&source->sessList);
  301.                 while (tsn = NEXT(wsn)) {
  302.                     sn = REMHEAD(&memList);
  303.                     sn->addr = wsn->addr;
  304.                     XfqCopyObject(sn->addr);
  305.                     ADDTAIL(&session->sessList, sn);
  306.                     if (public) {
  307.                         sq = FindSiteQueue(sn->addr);
  308.                         sq->numSessions++;
  309.                     }
  310.                     wsn = tsn;
  311.                 }
  312.                 last = sn;
  313.             }
  314.             break;
  315.         case XQ_AddSorted:
  316.             if (ObjectType(tag->ti_Data) == XQO_ADDRESS) {
  317.                 sn = REMHEAD(&memList);
  318.                 sn->addr = (struct NetAddress *)tag->ti_Data;
  319.                 XfqCopyObject(sn->addr);
  320.                 AddSessNodeSorted(session, sn, last);
  321.                 if (public) {
  322.                     sq = FindSiteQueue(sn->addr);
  323.                     sq->numSessions++;
  324.                 }
  325.                 last = sn;
  326.             }
  327.             else {
  328.                 source = (struct Session *)tag->ti_Data;
  329.                 wsn = LAST(&source->sessList);
  330.                 while (tsn = PREV(wsn)) {
  331.                     sn = REMHEAD(&memList);
  332.                     sn->addr = wsn->addr;
  333.                     XfqCopyObject(sn->addr);
  334.                     AddSessNodeSorted(session, sn, last);
  335.                     if (public) {
  336.                         sq = FindSiteQueue(sn->addr);
  337.                         sq->numSessions++;
  338.                     }
  339.                     last = sn;
  340.                     wsn = tsn;
  341.                 }
  342.             }
  343.             break;
  344.         }
  345.     }
  346.     if (public) {
  347.         ReleaseSemaphore(&QueueLock);
  348.     }
  349.     SetErrorTags(tags);
  350.     return TRUE;
  351. }
  352.  
  353.  
  354.  
  355. void __saveds __asm LIBEndSession(register __a0 struct Session *session,
  356.     register __a1 void *object)
  357. /*
  358.  *    In:    session    A0        Session cookie to end session to
  359.  *            object    A1        Address/session to end session to
  360.  *
  361.  * Does:    Removes the address from the given session.  If the session is
  362.  *            a public session, then the address is removed globally and the
  363.  *            queue in question is scanned:
  364.  *
  365.  *            XQ_IMMEDIATE nodes are marked as cancelled.
  366.  *            XQ_SENDLATER nodes have the SENDLATER flag cleared.
  367.  *
  368.  *            The object may be a site or a session.  If a session, then
  369.  *            all sites on that session will be removed from the first session.
  370.  *            The object may also be NULL, in which case all objects are
  371.  *            removed from the session.
  372.  */
  373. {
  374. struct SessNode *sn, *wsn, *tsn;
  375. struct SiteNode *sq;
  376. struct Session *source;
  377. BOOL public;
  378.  
  379.     if (!object) {
  380.         object = session;
  381.     }
  382.     public = !(session->flags & XQSESS_PRIVATE);
  383.     if (public) {
  384.         ObtainSemaphore(&QueueLock);
  385.     }
  386.     if (ObjectType(object) == XQO_ADDRESS) {
  387.         sn = FindSessNode(session, object);
  388.         if (sn) {
  389.             REMOVE(sn);
  390.             if (public) {
  391.                 sq = FindSiteQueue(object);
  392.                 if (!--sq->numSessions) {
  393.                     SessionDownQueue(sq);
  394.                 }
  395.             }
  396.             XfqDropObject(sn->addr);
  397.             FreeMemory(sn);
  398.         }
  399.     }
  400.     else {
  401.         source = object;
  402.         wsn = FIRST(&source->sessList);
  403.         while (tsn = NEXT(wsn)) {
  404.             sn = FindSessNode(session, wsn->addr);
  405.             if (sn) {
  406.                 REMOVE(sn);
  407.                 if (public) {
  408.                     sq = FindSiteQueue(wsn->addr);
  409.                     if (!--sq->numSessions) {
  410.                         SessionDownQueue(sq);
  411.                     }
  412.                 }
  413.                 XfqDropObject(sn->addr);
  414.                 FreeMemory(sn);
  415.             }
  416.             wsn = tsn;
  417.         }
  418.     }
  419.     if (public) {
  420.         ReleaseSemaphore(&QueueLock);
  421.     }
  422. }
  423.  
  424.  
  425. void __saveds __asm LIBSortSession(register __a0 struct Session *session,
  426.     register __a1 struct TagItem *tags)
  427. /*
  428.  *    In:    session    A0        Session cookie to sort
  429.  *            tags        A1        Taglist controlling operation
  430.  *
  431.  *    Does:    Puts all of the addresses in the session in sorted order.
  432.  *            No tags are currently defined.
  433.  */
  434. {
  435. struct MinList tempList;
  436. struct SessNode *sn, *last;
  437.  
  438.     tempList = session->sessList;
  439.     NEWLIST(&session->sessList);
  440.     last = NULL;
  441.     while (sn = REMHEAD(&tempList)) {
  442.         AddSessNodeSorted(session, sn, last);
  443.         last = sn;
  444.     }
  445.     SetErrorTags(tags);
  446. }
  447.  
  448.  
  449. void __saveds __asm LIBWalkSessionCallBack(
  450.     register __a0 struct Session *session,
  451.     register __a1 struct TagItem *tags,
  452.     register __a4 void *globals)
  453. /*
  454.  *    In:    object    A0        Address/session cookie to walk
  455.  *            tags        A1        User/system tags
  456.  *            globals    A4        Pointer to caller's global vector
  457.  *
  458.  *    Does:    Walks the session cookie, calling a user-supplied function
  459.  *            for each address.  The user function is given as a standard
  460.  *            hook structure and is called as follows:
  461.  *
  462.  *            continue = func(hook, address, data) where
  463.  *
  464.  *            hook        A0        Pointer to hook structure passed in
  465.  *            address    A2        Pointer to current address
  466.  *            data        A1        User data value passed in to this function
  467.  *
  468.  *            It must return TRUE to continue the walk, FALSE otherwise.
  469.  *
  470.  *            Valid tags are:
  471.  *            XQ_Reverse        Set to TRUE to walk in reverse direction
  472.  *            XQ_CallBack        Data is pointer to user callback hook
  473.  *            XQ_SessOnly        Only walk global nodes that have sessions up
  474.  *
  475.  *            If the session to walk is NULL, then the global session list
  476.  *            is walked.
  477.  */
  478. {
  479. struct Hook *hook;
  480. BOOL reverse, sessOnly;
  481. struct SessNode *sn, *tsn;
  482. struct SiteNode *sq;
  483.  
  484.     hook = (struct Hook *)GetTagData(XQ_CallBack, NULL, tags);
  485.     reverse = GetTagData(XQ_Reverse, FALSE, tags);
  486.     sessOnly = GetTagData(XQ_SessOnly, TRUE, tags);
  487.     if (session) {
  488.         if (reverse) {
  489.             sn = LAST(&session->sessList);
  490.             while (tsn = PREV(sn)) {
  491.                 if (!CallHookRes(hook, sn->addr, tags, globals)) {
  492.                     break;
  493.                 }
  494.                 sn = tsn;
  495.             }
  496.         }
  497.         else {
  498.             sn = FIRST(&session->sessList);
  499.             while (tsn = NEXT(sn)) {
  500.                 if (!CallHookRes(hook, sn->addr, tags, globals)) {
  501.                     break;
  502.                 }
  503.                 sn = tsn;
  504.             }
  505.         }
  506.     }
  507.     else {
  508.         ObtainSemaphore(&QueueLock);
  509.         if (reverse) {
  510.             sq = LAST(&QueueList);
  511.             while (PREV(sq)) {
  512.                 if ((!sessOnly || sq->numSessions) &&
  513.                     (!CallHookRes(hook, sq->site, tags, globals))) {
  514.                         break;
  515.                 }
  516.                 sq = PREV(sq);
  517.             }
  518.         }
  519.         else {
  520.             sq = FIRST(&QueueList);
  521.             while (NEXT(sq)) {
  522.                 if ((!sessOnly || sq->numSessions) &&
  523.                     (!CallHookRes(hook, sq->site, tags, globals))) {
  524.                         break;
  525.                 }
  526.                 sq = NEXT(sq);
  527.             }
  528.         }
  529.         ReleaseSemaphore(&QueueLock);
  530.     }
  531. }
  532.  
  533.